/*
 * @Author:
 * @Date: 2023-03-20 19:27:00
 * @LastEditors: xxx
 * @LastEditTime: 2023-08-29 11:44:01
 * @FilePath: \hart\hart\hart.c
 * @Description: hart模块接口
 * email:
 * Copyright (c) 2023 by xxx, All Rights Reserved.
 */

#include "./inc/hart.h"

#ifdef SLAVE
#include "./slave/inc/hart_slave_frame.h"
#endif

static hart_init_t handle;
static hart_response_t response;
#ifdef STM32
BOOL(*hart_command_ptr_arr[HART_COMMAND_MAX])
(const hart_command_req_t *const req, hart_response_t *resp);
#else
BOOL(*hart_command_ptr_arr[HART_COMMAND_MAX])
(const hart_command_req_t *const req, hart_response_t *resp);
#endif
/**
 * @brief hart模块初始化
 * @param {hart_init_t} *init: 初始化参数
 * @return: TRUE: 初始化成功
 *          FALSE: 初始化失败
 */
BOOL hart_init(const hart_init_t *const init)
{
    // 将初始数据赋值给handle
    if (!DBG_ASSERT(init != NULL __DBG_LINE))
        return FALSE;
    osel_memcpy((uint8_t *)&handle, (uint8_t *)init, sizeof(hart_init_t));

    // 检查参数
    if (!DBG_ASSERT((handle.dir == MODULE_MASTER) || (handle.dir == MODULE_SLAVE) __DBG_LINE))
        return FALSE;

    if (!DBG_ASSERT(handle.interface.response != NULL __DBG_LINE))
        return FALSE;

    // 缓存消息初始化
    hart_cache_init();
#ifdef MASTER
    if (handle.dir == MODULE_MASTER) // 主机模块初始化
    {
        handle.hart_module_u._master.address_bit = handle.master_address_bit;
        if (handle.hart_module_u._master.address_bit != HART_MASTER_ADDRESS)
        {
            handle.hart_module_u._master.address_bit = 0;
        }

        handle.hart_module_u._master.response_call = handle.interface.response;
        handle.hart_module_u._master.response = &response;
        if (!DBG_ASSERT(hart_master_init(&handle.hart_module_u._master) == TRUE __DBG_LINE))
            return FALSE;

#if MOCK == 1
        mock_master_attribute();
#endif
    }
#endif

#ifdef SLAVE
    hart_device_attribute.hart_protocol_version = &handle.hart_protocol_version;
    if (!DBG_ASSERT((hart_get_current_protocol_version() == HART_PROTOCOL_VERSION_5 ||
                     hart_get_current_protocol_version() == HART_PROTOCOL_VERSION_7) __DBG_LINE)) // 校验协议版本号，模块支持协议版本为5,7
        return FALSE;
    if (handle.dir == MODULE_SLAVE) // 从机模块初始化
    {
        if (!DBG_ASSERT(handle.interface.flash_read != NULL __DBG_LINE)) // 从机模块必须实现flash_read接口
            return FALSE;
        if (!DBG_ASSERT(handle.interface.flash_write != NULL __DBG_LINE)) // 从机模块必须实现flash_write接口
            return FALSE;
        if (!DBG_ASSERT(handle.interface.perform_self_test != NULL __DBG_LINE)) // 从机模块必须实现perform_self_test接口
            return FALSE;
        if (!DBG_ASSERT(handle.interface.device_reset != NULL __DBG_LINE)) // 从机模块必须实现device_reset接口
            return FALSE;
        if (!DBG_ASSERT(handle.interface.squawk_control != NULL __DBG_LINE)) // 从机模块必须实现squawk_control接口
            return FALSE;
        if (!DBG_ASSERT(handle.interface.armed != NULL __DBG_LINE)) // 从机模块必须实现armed接口
            return FALSE;

        handle.hart_module_u._slave.response_call = handle.interface.response;
        handle.hart_module_u._slave.response = &response;
        if (!DBG_ASSERT(hart_slave_init(&handle.hart_module_u._slave) == TRUE __DBG_LINE))
            return FALSE;

#ifdef STM32
        hart_slave_device_attribute_init();
        if (!DBG_ASSERT(handle.interface.set_dynamics != NULL __DBG_LINE)) // 从机模块必须动态数据接口
            return FALSE;
        BOOL epprom_res = FALSE;
        // 从flash中读取设备属性
        epprom_res = handle.interface.flash_read(HART_EEPROM_ADDRESS, (uint8_t *)&hart_device_attribute.flash_variable, sizeof(hart_storage_variable_t));
        if (epprom_res == FALSE)
        {
            if (!DBG_ASSERT(handle.interface.attribute_init != NULL __DBG_LINE))
                return FALSE;
            handle.interface.attribute_init();
        }
        // 从flash中读取用户自定义属性
        epprom_res = handle.interface.flash_read(HART_EEPROM_ADDRESS_USER, (uint8_t *)&hart_device_attribute.flash_variable_user, sizeof(hart_storage_variable_user_t));
        if (epprom_res == FALSE)
        {
            if (!DBG_ASSERT(handle.interface.attribute_user_init != NULL __DBG_LINE))
                return FALSE;
            handle.interface.attribute_user_init();
        }
        // 动态属性
        handle.interface.set_dynamics(&hart_device_attribute.dynamics);
#else
        mock_data();
        handle.interface.user_common_event = NULL;
#endif
    }
#endif

    return TRUE;
}

/**
 * @brief hart模块数据处理函数
 * @param {uint8_t} *rxBuf: 接收到的数据
 * @param {uint16_t} len: 接收到的数据长度
 * @return: TRUE: 处理成功
 *          FALSE: 处理失败
 */
BOOL hart_handle(uint8_t uart_index, uint8_t *rxBuf, uint16_t len)
{
    uint8_t xor = 0; // 异或校验
    uint8_t front = 0;
    if (!DBG_ASSERT(rxBuf != NULL __DBG_LINE))
        return FALSE;
    if (!DBG_ASSERT(len != 0 __DBG_LINE))
        return FALSE;

    if (!DBG_ASSERT((handle.dir == MODULE_MASTER) || (handle.dir == MODULE_SLAVE) __DBG_LINE))
        return FALSE;

    // 查找前导符
    while (len > 0)
    {
        if (*rxBuf != HART_PREAMBLE && front == HART_PREAMBLE)
            break;
        else
        {
            front = *rxBuf;
            rxBuf++;
            len--;
        }
    }

    if (len < 2) // 前导符后至少有2个字节
        return FALSE;

    xor = xor_compute(rxBuf, len - 1); // 异或校验

    if (xor != rxBuf[len - 1])
    {
        LOG_PRINT("[hart_handle] xro error");
        return FALSE; // 校验错误
    }

    // 根据模块工作模式将数据分发给对应的主机或从机处理
#ifdef MASTER
    if (handle.dir == MODULE_MASTER)
    {
        return hart_master_handle(rxBuf, len);
    }
#endif

#ifdef SLAVE
    if (handle.dir == MODULE_SLAVE)
    {
        return hart_slave_handle(uart_index, rxBuf, len);
    }
#endif
    return FALSE;
}

void hart_cache_data_send(uint64_t uuid)
{
    hart_cache_t *p;
    p = hart_cache_get(uuid);
    if (NULL != p)
    {
        LOG_PRINT("%d", p->uuid);
#ifdef SLAVE
        hart_slave_device_send(p);
#endif
    }
}

/**
 * @brief flash写入 hart内部使用
 * @param {uint32_t} addr
 * @param {uint8_t} *data
 * @param {uint16_t} len
 * @return {*}
 */
BOOL hart_storage_write(hart_eeprom_address_e addr, uint8_t *data, uint16_t len)
{
    return handle.interface.flash_write(addr, data, len);
}
/**
 * @brief falsh读取  hart内部使用
 * @param {uint32_t} addr
 * @param {uint8_t} *data
 * @param {uint16_t} len
 * @return {*}
 */
BOOL hart_storage_read(hart_eeprom_address_e addr, uint8_t *data, uint16_t len)
{
    return handle.interface.flash_read(addr, data, len);
}

/**
 * @brief 自检
 * @return {*}
 */
void perform_self_test(void)
{
#ifdef SLAVE
    hart_device_attribute.device_status.busy = TRUE;
    hart_device_attribute.internal = HART_INTERNAL;
    handle.interface.perform_self_test();
#endif
}

/**
 * @brief 自检完成
 * @return {*}
 */
void perform_self_test_finish(void)
{
#ifdef SLAVE
    hart_device_attribute.device_status.busy = FALSE;
    hart_device_attribute.internal = HART_INTERNAL;
#endif
}

/**
 * @brief 设备复位
 * @return {*}
 */
void device_reset(void)
{
    hart_device_attribute.device_status.reset = TRUE;
    hart_device_attribute.internal = HART_INTERNAL;
    handle.interface.device_reset();
}

/**
 * @brief 呼叫
 * @param {BOOL} open
 * @param {uint8_t} second
 * @return {*}
 */
void squawk_control(BOOL open, uint8_t second)
{
    handle.interface.squawk_control(open, second);
}

/**
 * @brief  技术人员按下一个特殊的按钮或按钮组合，指示从机应响应command74
 * @return {*}
 */
BOOL armed(void)
{
    return handle.interface.armed();
}

/**
 * @brief 设置实时时钟
 * @param {uint8_t} year
 * @param {uint8_t} month
 * @param {uint8_t} day
 * @param {uint8_t} hour
 * @param {uint8_t} min
 * @param {uint8_t} sec
 * @return {*}
 * @note
 */
void set_real_time_clock(uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec)
{
    if (handle.interface.set_real_time_clock == NULL)
        return;

    handle.interface.set_real_time_clock(year, month, day, hour, min, sec);
}

/**
 * @brief 获取实时时钟
 * @param {uint8_t} *year
 * @param {uint8_t} *month
 * @param {uint8_t} *day
 * @param {uint8_t} *hour
 * @param {uint8_t} *min
 * @param {uint8_t} *sec
 * @return {*}
 * @note
 */
void get_real_time_clock(uint8_t *year, uint8_t *month, uint8_t *day, uint8_t *hour, uint8_t *min, uint8_t *sec)
{
    if (handle.interface.get_real_time_clock == NULL)
        return;

    handle.interface.get_real_time_clock(year, month, day, hour, min, sec);
}

BOOL user_common_event(hart_interface_user_event_e event, const void *const data)
{
    if (handle.interface.user_common_event == NULL)
        return FALSE;
    return handle.interface.user_common_event(event, data);
}

BOOL get_device_lock(void)
{
    return hart_device_attribute.flash_variable.lock_code == LOCK_DEVICE_CODE_0 ? FALSE : TRUE;
}
